package com.ns.school.common.utils;

import com.ns.school.common.constant.StaticVar;
import com.ns.school.common.exception.MyException;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 集合工具类
 *
 * @author Spark
 */
public class CollUtil extends CollectionUtils {

    /**
     * 使用 Map按key进行排序--升序
     *
     * @param oriMap
     * @return
     */
    public static <T> Map<String, T> sortMapByKey(Map<String, T> oriMap) {
        if (oriMap == null || oriMap.isEmpty()) {
            return null;
        }
        Map<String, T> sortedMap = new TreeMap<>(Comparator.naturalOrder());
        sortedMap.putAll(oriMap);
        return sortedMap;
    }

    /**
     * 使用 Map按value进行排序--升序
     *
     * @param map
     * @return
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortMapByValue(Map<K, V> map) {
        List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
        list.sort(Map.Entry.comparingByValue());
        // 另外一种写法：Collections.sort(list, (o1, o2) -> o1.getValue().compareTo(o2.getValue()));
        Map<K, V> result = new LinkedHashMap<>();
        for (Map.Entry<K, V> entry : list) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    /**
     * 使用 Map按value进行排序--降序
     *
     * @param map
     * @return
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortMapByValueDesc(Map<K, V> map) {
        List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
        list.sort((o1, o2) -> {
            int compare = (o1.getValue()).compareTo(o2.getValue());
            return -compare;
        });
        // 另外一种写法：Collections.sort(list, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));
        Map<K, V> result = new LinkedHashMap<>();
        for (Map.Entry<K, V> entry : list) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    /**
     * List排序-升序
     *
     * @param list
     * @param <T>
     */
    public static <T extends Comparable<? super T>> void sort(List<T> list) {
        Collections.sort(list);
    }

    /**
     * List排序-降序
     *
     * @param list
     * @param <T>
     */
    public static <T extends Comparable<? super T>> void sortDesc(List<T> list) {
        Collections.sort(list);
        Collections.reverse(list);
    }

    /**
     * 判断集合是否为空
     *
     * @param collection
     * @return
     */
    public static boolean isEmpty(Collection<?> collection) {
        return (collection == null || collection.isEmpty());
    }

    /**
     * 判断Map是否为空
     *
     * @param map
     * @return
     */
    public static boolean isEmpty(Map<?, ?> map) {
        return (map == null || map.isEmpty());
    }

    /**
     * 判断数组是否为空
     *
     * @param arr
     * @return
     */
    public static boolean isEmpty(Object[] arr) {
        return (arr == null || arr.length == 0);
    }

    /**
     * 判断集合是否为空
     *
     * @param collection
     * @return
     */
    public static boolean notEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 判断Map是否为空
     *
     * @param map
     * @return
     */
    public static boolean notEmpty(Map<?, ?> map) {
        return !isEmpty(map);
    }

    /**
     * 判断集合是否有内容
     *
     * @param collection
     * @return
     */
    public static boolean hasContent(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 判断Map是否有内容
     *
     * @param map
     * @return
     */
    public static boolean hasContent(Map<?, ?> map) {
        return !isEmpty(map);
    }

    /**
     * 判断数组是否有内容
     *
     * @param arr
     * @return
     */
    public static boolean hasContent(Object[] arr) {
        return !isEmpty(arr);
    }

    /**
     * 将对象添加到List中,并保证不重复
     *
     * @param list
     * @param obj
     */
    public static <T> void addNoRepeat(List<T> list, T obj) {
        if (list == null) {
            throw new MyException("list is null");
        }
        if (list.isEmpty() || !list.contains(obj)) {
            list.add(obj);
        }
    }

    /**
     * 根据指定的分隔符将String类型的List内容连接成String
     *
     * @param list
     * @param spit
     * @return
     */
    public static String parseList2Str(List<String> list, String spit) {
        if (CollUtil.isEmpty(list) || StrUtil.isEmpty(spit)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (String string : list) {
            if (i == 0) {
                sb.append(string);
                i++;
            } else {
                sb.append(spit).append(string);
            }
        }
        return sb.toString();
    }

    /**
     * 根据指定的分隔符将String类型的List内容连接成String
     *
     * @param list
     * @param spit
     * @return
     */
    public static String parseIntList2Str(List<Integer> list, String spit) {
        if (CollUtil.isEmpty(list) || StrUtil.isEmpty(spit)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (Integer string : list) {
            if (i == 0) {
                sb.append(string);
                i++;
            } else {
                sb.append(spit).append(string);
            }
        }
        return sb.toString();
    }

    /**
     * 根据分隔符`,`将String转成List(str)
     *
     * @param str
     * @return
     */
    public static List<String> parseStr2List(String str) {
        return parseStr2List(str, StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成List(str)
     *
     * @param str
     * @param spit
     * @return
     */
    public static List<String> parseStr2List(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        List<String> list = new ArrayList<>();
        for (String v : splits) {
            if (StrUtil.hasText(v)) {
                list.add(v);
            }
        }
        return list;
    }

    /**
     * 根据分隔符`,`将String转成Set(str)
     *
     * @param str
     * @return
     */
    public static Set<String> parseStr2Set(String str) {
        return parseStr2Set(str, StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成Set(str)
     *
     * @param str
     * @param spit
     * @return
     */
    public static Set<String> parseStr2Set(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        Set<String> list = new LinkedHashSet<>();
        for (String v : splits) {
            if (StrUtil.hasText(v)) {
                list.add(v);
            }
        }
        return list;
    }

    /**
     * 根据分隔符`,`将String转成List(int)
     *
     * @param str
     * @return
     */
    public static List<Integer> parseIntStr2List(String str) {
        return parseIntStr2List(str, StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成List(int)
     *
     * @param str
     * @param spit
     * @return
     */
    public static List<Integer> parseIntStr2List(String str, String spit) {
        return parseIntStr2List(str, spit, false);
    }

    /**
     * 根据指定的分隔符将String转成List(int)
     *
     * @param str
     * @param spit
     * @return
     */
    public static List<Integer> parseIntStr2List(String str, String spit, boolean allowNull) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        List<Integer> list = new ArrayList<>();
        for (String v : splits) {
            if (StrUtil.hasText(v)) {
                list.add(Integer.parseInt(v));
            } else if (allowNull) {
                list.add(null);
            }
        }
        return list;
    }

    /**
     * 根据分隔符`,`将String转成List(Long)
     *
     * @param str
     * @return
     */
    public static List<Long> parseLongStr2List(String str) {
        return parseLongStr2List(str, StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成List(Long)
     *
     * @param str
     * @param spit
     * @return
     */
    public static List<Long> parseLongStr2List(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        List<Long> list = new ArrayList<>();
        for (String v : splits) {
            if (StrUtil.hasText(v)) {
                list.add(Long.parseLong(v));
            }
        }
        return list;
    }

    /**
     * 根据分隔符`,`将String转成Set(int)
     *
     * @param str
     * @return
     */
    public static Set<Integer> parseIntStr2Set(String str) {
        return parseIntStr2Set(str, StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成Set(int)
     *
     * @param str
     * @param spit
     * @return
     */
    public static Set<Integer> parseIntStr2Set(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        Set<Integer> list = new LinkedHashSet<>();
        for (String v : splits) {
            if (StrUtil.hasText(v)) {
                list.add(Integer.parseInt(v));
            }
        }
        return list;
    }

    /**
     * 根据分隔符`,`将String转成Set(Long)
     *
     * @param str
     * @return
     */
    public static Set<Long> parseLongStr2Set(String str) {
        return parseLongStr2Set(str, StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成Set(Long)
     *
     * @param str
     * @param spit
     * @return
     */
    public static Set<Long> parseLongStr2Set(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        Set<Long> list = new LinkedHashSet<>();
        for (String v : splits) {
            if (StrUtil.hasText(v)) {
                list.add(Long.parseLong(v));
            }
        }
        return list;
    }

    /**
     * 根据分隔符`,`将String转成List(Double)
     *
     * @param str
     * @return
     */
    public static List<Double> parseDoubleStr2List(String str) {
        return parseDoubleStr2List(str, StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成List(int)
     *
     * @param str
     * @param spit
     * @return
     */
    public static List<Double> parseDoubleStr2List(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        List<Double> list = new ArrayList<>();
        for (String v : splits) {
            if (StrUtil.hasText(v)) {
                list.add(Double.parseDouble(v));
            }
        }
        return list;
    }

    /**
     * 根据指定的分隔符将String转成数组
     *
     * @param str
     * @param spit
     * @return
     */
    public static Long[] parseStr2LongArr(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        Long[] t = new Long[splits.length];
        for (int i = 0; i < splits.length; i++) {
            String v = splits[i];
            t[i] = Long.parseLong(v);
        }
        return t;
    }

    /**
     * 根据指定的分隔符将String转成数组
     *
     * @param str
     * @param spit
     * @return
     */
    public static Integer[] parseStr2IntArr(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        String[] splits = str.split(spit);
        Integer[] t = new Integer[splits.length];
        for (int i = 0; i < splits.length; i++) {
            String v = splits[i];
            t[i] = Integer.parseInt(v);
        }
        return t;
    }

    /**
     * 根据指定的分隔符将String转成数组
     *
     * @param str
     * @return
     */
    public static String[] parseStr2Arr(String str) {
        if (StrUtil.isEmpty(str)) {
            return null;
        }
        return str.split(StaticVar.COMMA);
    }

    /**
     * 根据指定的分隔符将String转成数组
     *
     * @param str
     * @param spit
     * @return
     */
    public static String[] parseStr2Arr(String str, String spit) {
        if (StrUtil.isEmpty(str) || StrUtil.isEmpty(spit)) {
            return null;
        }
        return str.split(spit);
    }

    /**
     * 判断list1里是否存在一个元素在list2里面也存在
     *
     * @param list1
     * @param list2
     * @return
     */
    public static boolean theOneIsOnTwo(List<Integer> list1, List<Integer> list2) {
        if (StrUtil.isEmpty(list1) || StrUtil.isEmpty(list2)) {
            return false;
        }
        for (Integer v1 : list1) {
            if (v1 != null) {
                for (Integer v2 : list2) {
                    if (v1.equals(v2)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * List重复项去除
     *
     * @param list
     */
    public static <T> List<T> removeRepeat(final List<T> list) {
        if (isEmpty(list)) {
            return null;
        }
        // 只有一个元素的时候直接返回,无需去重
        if (list.size() == 1) {
            return list;
        }
        LinkedHashSet<T> set = new LinkedHashSet<>(list);
        list.clear();
        list.addAll(set);
        return list;
    }

    /**
     * List装String  "",""
     *
     * @param strList
     * @return
     */
    public static String convertListToString(List<String> strList) {
        StringBuilder sb = new StringBuilder();
        if (notEmpty(strList)) {
            for (int i = 0; i < strList.size(); i++) {
                if (i == 0) {
                    sb.append("'").append(strList.get(i)).append("'");
                } else {
                    sb.append(",").append("'").append(strList.get(i)).append("'");
                }
            }
        }
        return sb.toString();
    }

    /**
     * 比较两个List是否相等
     *
     * @param one
     * @param two
     * @return
     */
    public static <T> boolean equals(final List<T> one, final List<T> two) {
        if (one == null && two == null) {
            return true;
        }

        if (one == null || two == null || one.size() != two.size()) {
            return false;
        }

        List<T> copy1 = new ArrayList<>(one);
        List<T> copy2 = new ArrayList<>(two);

        copy1.sort(Comparator.comparing(T::hashCode));
        copy2.sort(Comparator.comparing(T::hashCode));
        return one.equals(two);
    }

    /**
     * 求两个集合交集
     *
     * @param arr1
     * @param arr2
     * @return
     */
    public static <T> List<T> intersection(final List<T> arr1, final List<T> arr2) {
        if (arr1 == null || arr2 == null) {
            return null;
        }
        List<T> r = new ArrayList<>();
        arr1.forEach(a1 -> {
            if (arr2.contains(a1)) {
                r.add(a1);
            }
        });
        return r;
    }

    /**
     * 求两个集合交集
     *
     * @param set1
     * @param set2
     * @return
     */
    public static <T> Set<T> intersection(final Set<T> set1, final Set<T> set2) {
        if (set1 == null || set2 == null) {
            return null;
        }
        Set<T> r = new HashSet<>();
        set1.forEach(s1 -> {
            if (set2.contains(s1)) {
                r.add(s1);
            }
        });
        return r;
    }

    /**
     * 新建一个ArrayList
     *
     * @param <T>    集合元素类型
     * @param values 数组
     * @return ArrayList对象
     * @see #toList(Object[])
     */
    @SafeVarargs
    public static <T> ArrayList<T> newArrayList(T... values) {
        return toList(values);
    }

    /**
     * 新建一个ArrayList
     *
     * @param <T>    集合元素类型
     * @param values 数组
     * @return ArrayList对象
     */
    @SafeVarargs
    public static <T> ArrayList<T> toList(T... values) {
        return (ArrayList<T>) list(false, values);
    }

    /**
     * 新建一个List
     *
     * @param <T>      集合元素类型
     * @param isLinked 是否新建LinkedList
     * @param values   数组
     * @return List对象
     * @since 4.1.2
     */
    @SafeVarargs
    public static <T> List<T> list(boolean isLinked, T... values) {
        if (isEmpty(values)) {
            return list(isLinked);
        }
        final List<T> arrayList = isLinked ? new LinkedList<>() : new ArrayList<>(values.length);
        Collections.addAll(arrayList, values);
        return arrayList;
    }

    /**
     * 取出集合中第一个元素
     *
     * @param col 集合实例
     * @param <E> 集合中元素类型
     * @return 泛型类型
     */
    public static <E> E getFirst(Collection<E> col) {
        if (notEmpty(col)) {
            return col.iterator().next();
        }
        return null;
    }
}
